package com.ruoyi.flow.common.utils;

import org.apache.commons.lang3.StringUtils;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;

import java.io.*;
import java.util.List;
import java.util.Objects;

public class XmlUtils {
    private XmlUtils() {
    }

    /**
     * 创建Document
     *
     * @param classPathFileName 基于classpath的文件路径
     * @return
     */
    public static Document parse(String classPathFileName) {
        checkArgument(StringUtils.isNotEmpty(classPathFileName), "classPathFileName must not be null.");
        try {
            SAXReader reader = new SAXReader();
            Document document = reader.read(new File(XmlUtils.class.getResource("/").getPath() + classPathFileName));
            return document;
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Document parse(File xmlFile) {
        checkArgument(xmlFile != null && xmlFile.isFile() && xmlFile.exists() && xmlFile.canRead(), "xml文件不存在或者不可读或者不是有效的文件，请确认");
        try {
            SAXReader reader = new SAXReader();
            return reader.read(xmlFile);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Document parse(InputStream in) {
        checkArgument(Objects.nonNull(in));
        try {
            SAXReader reader = new SAXReader();
            return reader.read(in);
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取根节点
     *
     * @param document
     * @return
     */
    public static Element getRootElement(Document document) {
        checkArgument(Objects.nonNull(document));
        return document.getRootElement();
    }

    /**
     * 根据xpath获取单个元素
     *
     * @param document
     * @param xpath    从根元素开始
     * @return
     */
    public static Node getElement(Document document, String xpath) {
        checkArgument(Objects.nonNull(document));
        checkArgument(StringUtils.isNotEmpty(xpath));
        return document.selectSingleNode(xpath);
    }

    public static List<Node> getElements(Document document, String xpath) {
        checkArgument(Objects.nonNull(document));
        checkArgument(StringUtils.isNotEmpty(xpath));
        return document.selectNodes(xpath);
    }

    /**
     * 获取某个元素的某个属性的值
     *
     * @param document
     * @param xpath
     * @param attributeName
     * @return
     */
    public static String getAttributeValue(Document document, String xpath, String attributeName) {
        checkArgument(Objects.nonNull(document));
        checkArgument(StringUtils.isNotEmpty(xpath));
        Node node = getElement(document, xpath);
        checkState(node != null, "Get node by xpath {} from xml file {} is null.", xpath,document.getName());
        return getAttributeValue(node, attributeName);
    }

    public static String getAttributeValue(Node node, String attributeName) {
        checkArgument(Objects.nonNull(node));
        checkArgument(StringUtils.isNotEmpty(attributeName));
        return node.valueOf("@" + attributeName);
    }

    public static List<Node> getChildren(Node currentNode, String xpath) {
        checkArgument(Objects.nonNull(currentNode));
        checkArgument(StringUtils.isNotEmpty(xpath));
        return currentNode.selectNodes(xpath);
    }


    public static Node getChild(Node currentNode, String xpath) {
        checkArgument(Objects.nonNull(currentNode));
        checkArgument(StringUtils.isNotEmpty(xpath));
        return currentNode.selectSingleNode(xpath);
    }

    public static void main(String[] args) {
        Document document = XmlUtils.parse("/processes/ExpenseModel.xml");
        Node node = document.selectSingleNode("/definitions/process");
        System.out.println(node);
        System.out.println(getAttributeValue(document, "/definitions/process", "id"));

    }
}
